package arcane.object.game.map;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import arcane.object.collections.Dateable;
import arcane.object.collections.Node;

import com.golden.gamedev.object.background.abstraction.AbstractTileBackground;

/**
 * This class is used to establish links between maps. The time its loaded into
 * memory is calculated, as is every time its used subsequently. If a map isn't
 * loaded into memory after a given period, it should be removed from memory.
 * This helps control memory consumption.
 * 
 * @author Will
 * 
 */
public class LinkedMap extends AbstractTileBackground implements Dateable {
	public static final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
	// Those layers to be rendered beneath actors
	int LOWER_LAYERS = 1;
	long age;
	Tile[][] layer;
	private String imgName;
	BufferedImage[] imgs;
	boolean[][] passable;
	private String mapName;

	public static final int UPPER_TILES = 0, LOWER_TILES = 1, BOTH_TILES = 3;
	public int RENDER_TILE = LOWER_TILES;

	public LinkedMap() {
		this(0, 0, "");
	}

	public LinkedMap(int w, int h, String imgName) {
		super(w, h, 32, 32);
		this.imgName = imgName;
		layer = new Tile[h][w];
		for (int i = 0; i < h; i++)
			for (int j = 0; j < w; j++) {
				layer[i][j] = new Tile(new int[] { 0 });
			}
		passable = new boolean[][] { { true, true, true, true } };
	}

	public void initMap() {
		age = System.currentTimeMillis();
	}

	public Tile[][] getTiles() {
		return layer;
	}

	public boolean[][] getPassable() {
		return passable;
	}

	public void setPassable(boolean[][] passable) {
		this.passable = passable;
	}

	public void render(Graphics2D g, int xbg, int ybg, int x, int y, int w,
			int h) {
		int x1 = 0, // coordinate counter
		y1 = 0;
		int x2 = x + w, // right boundary
		y2 = y + h; // bottom boundary
		int xTile = 0; // tile counter

		int yTile = this.getTileY();
		int offsetX = getOffsetX();
		int offsetY = getOffsetY();
		int tileHeight = getTileHeight();
		int tileWidth = getTileWidth();
		if (RENDER_TILE == LOWER_TILES || RENDER_TILE == BOTH_TILES) {
			for (y1 = y - offsetY; y1 < y2; y1 += tileHeight) {
				xTile = this.getTileX();
				for (x1 = x - offsetX; x1 < x2; x1 += tileWidth) {
					this.renderLowerTile(g, xTile, yTile, x1, y1);
					xTile++;
				}
				yTile++;
			}
		}
		if (RENDER_TILE == UPPER_TILES || RENDER_TILE == BOTH_TILES) {
			for (y1 = y - offsetY; y1 < y2; y1 += tileHeight) {
				xTile = this.getTileX();
				for (x1 = x - offsetX; x1 < x2; x1 += tileWidth) {
					this.renderUpperTile(g, xTile, yTile, x1, y1);
					xTile++;
				}
				yTile++;
			}
		}
	}

	public void renderTile(Graphics2D g, int tileX, int tileY, int x, int y) {
	}

	public void renderUpperTile(Graphics2D g, int tileX, int tileY, int x, int y) {
		int[] l = layer[tileY][tileX].getLayers();
		for (int i = LOWER_LAYERS; i < l.length; i++) {
			g.drawImage(imgs[l[i]], x, y, null);
		}
	}

	public void renderLowerTile(Graphics2D g, int tileX, int tileY, int x, int y) {
		System.out.println(tileX+" "+tileY);
		int[] l = layer[tileY][tileX].getLayers();
		for (int i = 0; i < l.length && i < LOWER_LAYERS; i++) {
			g.drawImage(imgs[l[i]], x, y, null);
		}
	}

	public boolean isPassable(int tileX, int tileY, int dir) {
		int[] layers = layer[tileY][tileX].getLayers();
		for (int i = 0; i < layers.length; i++) {
			int l = layers[i];
			for (int j = 0; j < 4; j++)
				if (!passable[l][j])
					return false;
		}
		return true;
	}

	public void setImages(BufferedImage[] imgs) {
		this.imgs = imgs;
	}
	
	public String getImageName(){
		return imgName;
	}

	public void setLayers(Tile[][] layer) {
		this.layer = layer;
	}

	public Tile[][] getLayers() {
		return layer;
	}

	public int getTileAt(int tileX, int tileY, int layer) {
		return this.layer[tileY][tileX].getLayers()[layer];
	}

	public long getBirthDate() {
		return age;
	}

	public String getName() {
		return mapName;
	}

	public void setName(String name) {
		this.mapName = name;
	}
}